/**
 * 
 */
package kr.co.insoft.publicmesh.controller.orchestration;

import kr.co.insoft.core.constant.HATypes;
import kr.co.insoft.core.model.orchestration.CompositeEntityModel;
import kr.co.insoft.core.model.orchestration.CompositeStackEntityModel;
import kr.co.insoft.core.model.orchestration.OrchestrationResultModel;
import kr.co.insoft.core.model.orchestration.ProjectEntityModel;
import kr.co.insoft.core.model.orchestration.ServiceEntityModel;
import kr.co.insoft.core.service.configration.connection.ConnectionService;
import kr.co.insoft.core.service.orchestration.OrchestrationService;
import kr.co.insoft.framework.exceptions.ExceptionCode;
import kr.co.insoft.framework.exceptions.NotFoundException;
import kr.co.insoft.framework.exceptions.ServiceException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

/**
 * Service / Group / Tier / VMGroup / HAgroup / Instance 관리 Controller
 * 
 * @author IN-SOFT Inc. GoodwillDD(sylee@in-soft.co.kr)
 * 
 */
@Controller
@RequestMapping(value = "orchestration/orchestration")
public class OrchestrationController {

	
	private static final Logger OrchestrationControllerLog = LoggerFactory
			.getLogger(OrchestrationController.class);
	
	final String TILES_PAGE_PREFIX = "tiles/orchestration";
	final String SINGLE_PAGE_PREFIX = "orchestration";

	@Autowired
	OrchestrationService orchestrationService;
	
	@Autowired
	ConnectionService connectionService;

	/**
	 * Tree 화면이 보여지는 메인
	 * 
	 * @param model
	 * @return
	 * @throws Exception
	 */
	@RequestMapping(value = "main")
	public String main(Model model) throws Exception {
		return TILES_PAGE_PREFIX + "/main";
	}

	@RequestMapping(value = "callForm", method = RequestMethod.POST)
	public String callingForm(Model model,
			@RequestParam("formType") String formType,
			@RequestParam("types") String types,
			@RequestParam("targetid") String targetid) throws Exception {
		switch (formType) {
		case "create":
			switch (types.toLowerCase()) {
			case "project":
				model.addAttribute(new ProjectEntityModel());
				break;
			case "service":
				model.addAttribute(orchestrationService
						.createServiceForm(targetid));
				break;
			case "vmcomposite":
				model.addAttribute("hatypes", HATypes.values());
				model.addAttribute(orchestrationService
						.createCompositeForm(targetid));
				break;
			case "vmcompositestack":
				model.addAttribute("connections", connectionService.getAllLists());
				model.addAttribute(orchestrationService.createStackForm(targetid));
				break;
			default:
				throw new NotFoundException(ExceptionCode.NOT_FOUND_EXCEPTION);
			}
			return SINGLE_PAGE_PREFIX + "/" + types + "/createForm";
		case "view":
			switch (types.toLowerCase()) {
			case "project":
				model.addAttribute(orchestrationService.getProject(targetid));
				break;
			case "service":
				model.addAttribute(orchestrationService.getService(targetid));
				break;
			case "vmcomposite":
				model.addAttribute("hatypes", HATypes.values());
				model.addAttribute(orchestrationService.getComposite(targetid));
				break;
			case "vmcompositestack":
				model.addAttribute(new CompositeStackEntityModel());
				break;
			default:
				throw new NotFoundException(ExceptionCode.NOT_FOUND_EXCEPTION);
			}
			return SINGLE_PAGE_PREFIX + "/" + types + "/view";
		case "edit":
			switch (types.toLowerCase()) {
			case "project":
				model.addAttribute(orchestrationService.getProject(targetid));
				break;
			case "service":
				model.addAttribute(orchestrationService.getService(targetid));
				break;
			case "vmcomposite":
				model.addAttribute("hatypes", HATypes.values());
				model.addAttribute(orchestrationService.getComposite(targetid));
				break;
			case "vmcompositestack":
				model.addAttribute(new CompositeStackEntityModel());
				break;
			default:
				throw new NotFoundException(ExceptionCode.NOT_FOUND_EXCEPTION);
			}
			return SINGLE_PAGE_PREFIX + "/" + types + "/edit";
		default:
			throw new NotFoundException(ExceptionCode.NOT_FOUND_EXCEPTION);
		}
	}

	@RequestMapping(value = "createProject", method = RequestMethod.POST, produces = { "application/json" })
	@ResponseStatus(HttpStatus.OK)
	public OrchestrationResultModel createProject(
			@ModelAttribute("projectEntityModel") ProjectEntityModel projectEntityModel,
			BindingResult bindingResult) {
		try {
			return orchestrationService.createProject(projectEntityModel);
		} catch (Exception e) {
			return new OrchestrationResultModel();
		}
	}

	@RequestMapping(value = "removeProject", method = RequestMethod.POST, produces = { "application/json" })
	public @ResponseBody ResponseEntity<Boolean> removeProject(
			@RequestParam("targetid") String targetid) {
		try {
			orchestrationService.removeProject(targetid);
			return new ResponseEntity<Boolean>(true, HttpStatus.OK);
		} catch (ServiceException e) {
			OrchestrationControllerLog.error("{}", e.getMessage());
			if ( ExceptionCode.HAVE_CHILD_NOT_DELETE.equals(e.getMessage())) {
				return new ResponseEntity<Boolean>(false, HttpStatus.OK);	
			}
			return new ResponseEntity<Boolean>(false, HttpStatus.BAD_REQUEST);
		}
	}
	
	@RequestMapping(value = "removeService", method = RequestMethod.POST, produces = { "application/json" })
	public @ResponseBody ResponseEntity<Boolean> removeService(
			@RequestParam("targetid") String targetid) {
		try {
			orchestrationService.removeService(targetid);
			return new ResponseEntity<Boolean>(true, HttpStatus.OK);
		} catch (ServiceException e) {
			if ( ExceptionCode.HAVE_CHILD_NOT_DELETE.equals(e.getMessage())) {
				return new ResponseEntity<Boolean>(false, HttpStatus.OK);	
			}
			return new ResponseEntity<Boolean>(false, HttpStatus.BAD_REQUEST);
		}
	}
	
	@RequestMapping(value = "removeComposite", method = RequestMethod.POST, produces = { "application/json" })
	public @ResponseBody ResponseEntity<Boolean> removeComposite(
			@RequestParam("targetid") String targetid) {
		try {
			orchestrationService.removeComposite(targetid);
			return new ResponseEntity<Boolean>(true, HttpStatus.OK);
		} catch (ServiceException e) {
			if ( ExceptionCode.HAVE_CHILD_NOT_DELETE.equals(e.getMessage())) {
				return new ResponseEntity<Boolean>(false, HttpStatus.OK);	
			}
			return new ResponseEntity<Boolean>(false, HttpStatus.BAD_REQUEST);
		}
	}

	@RequestMapping(value = "createService", method = RequestMethod.POST, produces = { "application/json" })
	@ResponseStatus(HttpStatus.OK)
	public OrchestrationResultModel createService(
			@ModelAttribute("serviceEntityModel") ServiceEntityModel serviceEntityModel,
			BindingResult bindingResult) {
		try {
			return orchestrationService.createService(serviceEntityModel);
		} catch (ServiceException e) {
			return new OrchestrationResultModel();
		}
	}

	@RequestMapping(value = "createComposite", method = RequestMethod.POST, produces = { "application/json" })
	@ResponseStatus(HttpStatus.OK)
	public OrchestrationResultModel createComposite(
			@ModelAttribute("compositeEntityModel") CompositeEntityModel compositeEntityModel,
			BindingResult bindingResult) {
		try {
			return orchestrationService.createComposite(compositeEntityModel);
		} catch (ServiceException e) {
			return new OrchestrationResultModel();
		}
	}
	
	@RequestMapping(value = "createStack", method = RequestMethod.POST, produces = { "application/json" })
	@ResponseStatus(HttpStatus.OK)
	public OrchestrationResultModel createStack(
			@ModelAttribute("compositeStackEntityModel") CompositeStackEntityModel compositeStackEntityModel,
			BindingResult bindingResult) {
		try {
			return orchestrationService.createStack(compositeStackEntityModel);
		} catch (ServiceException e) {
			return new OrchestrationResultModel();
		}
	}

}
